package com.novunda.platform.web;

import java.util.ArrayList;
import java.util.List;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.lang3.StringUtils;
import org.apache.shiro.authz.annotation.Logical;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.apache.shiro.authz.annotation.RequiresUser;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.servlet.mvc.support.RedirectAttributes;

import com.google.common.collect.Lists;
import com.novunda.platform.common.exception.NovException;
import com.novunda.platform.common.exception.ValidationErrorException;
import com.novunda.platform.common.utils.CheckNameUtil;
import com.novunda.platform.common.utils.PWDUtils;
import com.novunda.platform.common.utils.ParameterValidateUtil;
import com.novunda.platform.common.utils.PinYinUtil;
import com.novunda.platform.common.utils.StringKit;
import com.novunda.platform.common.utils.StringUtil;
import com.novunda.platform.common.utils.UserUtils;
import com.novunda.platform.common.web.controller.BaseController;
import com.novunda.platform.common.web.modal.Page;
import com.novunda.platform.entities.Office;
import com.novunda.platform.entities.Role;
import com.novunda.platform.entities.User;
import com.novunda.platform.enums.UserStateEnum;
import com.novunda.platform.services.PlatformService;
import com.novunda.platform.services.RoleService;
import com.novunda.platform.services.UserService;

import net.sourceforge.pinyin4j.format.exception.BadHanyuPinyinOutputFormatCombination;

/**
 * . 功能说明：账号管理controller
 * 
 * @author linfeng
 * @see 2016年9月22日
 * @version 1.0
 * @modify FJ
 */
@Controller
@RequestMapping("/sys/user")
public class UserController extends BaseController {

	/**
	 * . 用户列表url
	 */
	private final String USER_URL = "redirect:/sys/user/";

	/**
	 * . 平台service
	 */
	@Autowired
	private PlatformService platformService;

	/**
	 * . 用户service
	 */
	@Autowired
	private UserService userService;

	/**
	 * . 角色service
	 */
	@Autowired
	private RoleService roleService;

	/**
	 * . 功能说明：通过id获取用户，id为空则新建一个用户对象
	 * 
	 * @param id
	 *            用户id
	 * @return
	 */
	@ModelAttribute
	public User get(@RequestParam(required = false) Long id, Model model) {
		// id为空
		if (id != null) {
			return userService.getUser(id);
		} else {
			return new User();
		}
	}

	/**
	 * . 功能说明：查询账号列表
	 * 
	 * @param user
	 *            账号对象
	 * @param request
	 * @param response
	 * @param model
	 * @return
	 */
	@RequiresPermissions("sys:user:view")
	@RequestMapping({ "list", "" })
	public String list(User user, HttpServletRequest request, HttpServletResponse response, Model model) {
		try {
			Page<User> page = platformService.findUser(new Page<User>(request, response), user);
			List<User> userList = page.getList();
			List<User> sortUserList = new ArrayList<User>();
			int startIndex = (page.getPageNo() - 1) * page.getPageSize() + 1;
			for (User u : userList) {
				u.setIndex(startIndex++);
				sortUserList.add(u);
			}
			page.setList(sortUserList);
			model.addAttribute("page", page);
		} catch (Exception e) {
			LOG.error(e.getMessage(), e);
		}
		return "modules/sys/userList";
	}

	/**
	 * . 功能说明：添加、修改账号页面跳转
	 * 
	 * @param user
	 *            账号对象
	 * @param model
	 * @return
	 */
	@RequiresPermissions("sys:user:view")
	@RequestMapping(value = "form")
	public String form(User user, Model model) {
		if (null == user) {
			addMessage(model, "当前用户不存在");
			return USER_URL;
		}
		// 如果账号机构为空默认为当前登录人所属机构
		if (user.getCompany() == null || user.getCompany().getId() == null) {
			user.setCompany(UserUtils.getUser().getCompany());
		}
		// 该机构下的所有角色集合
		List<Role> allRoles = roleService.findRoleByOrg(user.getCompany().getId());
		// 当前登录人所拥有角色权限范围内的角色集合
		List<Role> list = platformService.findAllRole();
		List<Long> ids = new ArrayList<Long>();
		for (Role r : list) {
			ids.add(r.getId());
		}
		// 该用户所拥有的角色
		List<Long> userIds = new ArrayList<Long>();
		for (Role r : user.getRoleList()) {
			userIds.add(r.getId());
		}
		// 返回前台页面所选机构下该用户角色权限范围内查看的角色并且选中该用户已经拥有的角色
		List<Role> roleList = new ArrayList<Role>();
		for (Role role : allRoles) {
			long roleId = role.getId();
			// 如果该用户的角色权限范围内能查看的角色包含该角色，则添加进集合返回页面
			if (ids.contains(roleId)) {
				// 如果该用户拥有此角色，则选中
				if (userIds.contains(roleId)) {
					role.setChecked(true);
				}
				roleList.add(role);
			}
		}
		model.addAttribute("user", user);
		model.addAttribute("allRoles", roleList);
		return "modules/sys/userForm";
	}

	/**
	 * . 功能说明：添加帐号
	 *
	 * @param user
	 *            帐号
	 * @param request
	 *            http请求
	 * @param model
	 * @param redirectAttributes
	 * @return
	 */
	@RequiresPermissions(value={"sys:user:add","sys:user:edit"},logical=Logical.OR)
	@RequestMapping(value = "save", method = { RequestMethod.POST })
	public String save(User user, HttpServletRequest request, Model model, RedirectAttributes redirectAttributes) {
		try {
			// 服务端参数有效性验证
			if (!beanValidator(model, user)) {
				return form(user, model);
			}

			// 验证参数，返回拼装了机构编码的登录名
			String loginName = validateParams(user);

			// 修正引用赋值问题，不知道为何，Company和Office引用的一个实例地址，修改了一个，另外一个跟着修改。
			user.setCompany(new Office(StringKit.toLong(request.getParameter("company.id"))));
			user.setOffice(new Office(StringKit.toLong(request.getParameter("office.id"))));
			// 密码默认为123456
			user.setPassword(PWDUtils.entryptPassword("123456"));
			// 角色数据有效性验证，过滤不在授权内的角色
			List<Role> roleList = Lists.newArrayList();
			List<Long> roleIdList = user.getRoleIdList();
			for (Role r : platformService.findAllRole()) {
				if (roleIdList.contains(r.getId())) {
					roleList.add(r);
				}
			}
			user.setRoleList(roleList);

			// 保存用户信息
			user.setLoginName(loginName);
			platformService.saveUser(user);
			// 如果修改的是当前登录用户，清除当前用户的缓存
			if (user.getLoginName().equals(UserUtils.getUser().getLoginName())) {
				UserUtils.getCacheMap().clear();
				// 如果没有任何角色，跳转到首页
				if (null == user.getRoleList() || user.getRoleList().isEmpty()) {
					return "index";
				}
			}
			addMessage(redirectAttributes, "保存用户'" + user.getLoginName() + "'成功");
		} catch (ValidationErrorException e) {
			addMessage(model, "保存用户'" + user.getLoginName() + "'失败，" + e.getMessage());
			return form(user, model);
		} catch (BadHanyuPinyinOutputFormatCombination e) {
			LOG.error(e.getMessage(), e);
			addMessage(redirectAttributes, "保存用户" + user.getLoginName() + "失败，异常：" + e.getMessage());
			return form(user, model);
		} catch (Exception e) {
			LOG.error(e.getMessage(), e);
			addMessage(redirectAttributes, "保存用户" + user.getLoginName() + "失败，异常：" + e.getMessage());
			return form(user, model);
		}
		return USER_URL;
	}

	/**
	 * /** . 功能说明：get保存
	 * 
	 * @param user
	 * @param model
	 * @return
	 */
	@RequestMapping(value = "save", method = RequestMethod.GET)
	public String getSave(User user, Model model, HttpServletRequest request, HttpServletResponse response) {
		return list(user, request, response, model);
	}

	/**
	 * . 功能说明：验证参数
	 * 
	 * @param user
	 * @return
	 * @throws BadHanyuPinyinOutputFormatCombination
	 */
	private String validateParams(User user) throws BadHanyuPinyinOutputFormatCombination {
		String loginName = user.getLoginName();
		String oldEmail = "";
		// 如果id为空，则为新添加用户，需要验证用户名，设置状态，如果是修改则不需要
		if (null == user.getId()) {
			CheckNameUtil.checkNameIsNull("账号名", loginName);
			CheckNameUtil.checkUserNamePattern(loginName);
			String orgNamePinYin = PinYinUtil.getFirstSpell(user.getCompany().getName());
			String orgCode = orgNamePinYin + user.getCompany().getId();
			loginName = orgCode + "_" + loginName;
			if (platformService.getUserByLoginName(loginName) != null) {
				throw new ValidationErrorException("账号名已存在");
			}
			user.setState(UserStateEnum.NORMAL.ordinal());
		} else {
			// 如果为修改操作获取账号的修改之前的邮箱
			User oldUser = userService.getUser(user.getId());
			if (null != oldUser) {
				oldEmail = oldUser.getEmail();
			}
		}

		CheckNameUtil.checkEnChNumTwentyPattern("真实姓名", user.getRealName());
		// 如果手机不为空判断格式
		String mobile = user.getMobile();
		if (!StringUtil.isEmpty(mobile)) {
			ParameterValidateUtil.checkPhoneNum(mobile);
		}
		ParameterValidateUtil.checkEmail(user.getEmail());

		// 如果旧邮箱和新的不同表示修改了邮箱，验证新邮箱是否已经存在
		if (!oldEmail.equals(user.getEmail().trim())) {
			User userInfo = userService.findUserByEmailOrg(user.getEmail(), user.getCompany().getId());
			if (null != userInfo) {
				throw new ValidationErrorException("邮箱已经存在");
			}
		}

		return loginName;
	}

	/**
	 * . 功能说明：删除账号
	 * 
	 * @param id
	 *            账号id
	 * @param redirectAttributes
	 * @return
	 */
	@RequiresPermissions("sys:user:delete")
	@RequestMapping(value = "delete")
	public String delete(Long id, RedirectAttributes redirectAttributes) {
		try {
			User user = userService.getUser(id);
			if(user == null){
				addMessage(redirectAttributes, "该用户已经删除！");
				return USER_URL;
			}
			if (UserUtils.getUser().getId().equals(id)) {
				addMessage(redirectAttributes, "删除用户失败, 不允许删除当前用户");
			} else if (User.isAdmin(id)) {
				addMessage(redirectAttributes, "删除用户失败, 不允许删除超级管理员用户");
			} else {
				platformService.deleteUser(id);
				addMessage(redirectAttributes, "删除用户成功");
			}
		} catch (NovException e) {
			addMessage(redirectAttributes, "删除用户失败," + e.getMessage());
		}
		return USER_URL;
	}

	/**
	 * . 功能说明：获取用户信息
	 * 
	 * @param user
	 *            用户对象
	 * @param model
	 * @return
	 */
	@RequiresUser
	@RequestMapping(value = "info")
	public String info(User user, Model model) {
		User currentUser = UserUtils.getUser();
		// 如果账号名不为空
		if (StringUtils.isNotBlank(user.getRealName())) {
			currentUser = UserUtils.getUser(true);
			currentUser.setEmail(user.getEmail());
			currentUser.setPhone(user.getPhone());
			currentUser.setMobile(user.getMobile());
			currentUser.setRemarks(user.getRemarks());
			platformService.saveUser(currentUser);
			model.addAttribute("message", "保存用户信息成功");
		}
		model.addAttribute("user", currentUser);
		return "modules/sys/userInfo";
	}

	/**
	 * . 功能说明：获取选中用户
	 * 
	 * @param selectIds
	 *            选择id
	 * @param user
	 * @param request
	 * @param response
	 * @param model
	 * @return
	 */
	@RequiresUser
	@RequestMapping(value = "select")
	public String selectIds(String selectIds, User user, HttpServletRequest request, HttpServletResponse response,
			Model model) {
		Page<User> page = platformService.findUser(new Page<User>(request, response, 5), user);
		model.addAttribute("page", page);
		model.addAttribute("selectIds", selectIds);
		model.addAttribute("title", request.getParameter("title"));
		return "modules/sys/userSelect";
	}

	/**
	 * . 功能说明：检查账号名
	 * 
	 * @param oldLoginName
	 * @param id
	 * @return
	 */
	@ResponseBody
	// @RequiresPermissions("sys:user:edit")
	@RequestMapping("checkLoginName")
	public String checkLoginName(String oldLoginName, String id) {
		// 如果id不为空则为修改，不检查账号名
		if (!StringUtil.isEmpty(id)) {
			return "true";
		}
		// 检查账号名
		if (oldLoginName != null && platformService.getUserByLoginName(oldLoginName) == null) {
			return "true";
		}
		return "false";
	}

	/**
	 * . 功能说明：修改状态
	 *
	 * @param id
	 *            帐号id
	 * @param state
	 *            状态值
	 * @param redirectAttributes
	 * @return
	 */
	@RequestMapping(value = "changeState")
	@RequiresPermissions("sys:user:edit")
	public String changeState(Long id, int state, RedirectAttributes redirectAttributes) {
		User user = userService.getUser(id);
		// 如果账号不为空
		if (null == user) {
			addMessage(redirectAttributes, "修改状态失败, 该帐号不存在");
			return USER_URL;
		}
		// 如果账号状态已经为修改状态
		if (user.getState() == state) {
			int index = state == UserStateEnum.FREEZE.ordinal() ? UserStateEnum.FREEZE.ordinal()
					: UserStateEnum.NORMAL.ordinal();
			addMessage(redirectAttributes, "修改状态失败, 该帐号已经" + UserStateEnum.content(index));
			return USER_URL;
		}
		user.setState(state);
		userService.changeUserState(user);
		addMessage(redirectAttributes, "修改状态成功");
		return USER_URL;
	}

}
